#include <sys/epoll.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

#include "nio.h"

static inline int realEpoll(void *nio){
	int ep = (size_t)nio;
	return ep;
}

void* nioInit(){
	return (void *)(size_t)epoll_create(3);
}

int nioRegisteFd(void* nio, int fd, int actions){
	int epollFd = realEpoll(nio);
	struct epoll_event event;
	event.data.fd = fd;
	if(actions & ACTION_READ){
		event.events = EPOLLIN;
	}
	if(actions & ACTION_WRITE){
		event.events |= EPOLLOUT;
	}
	return epoll_ctl(epollFd, EPOLL_CTL_ADD, fd, &event);
}

int nioUnRegisteFd(void* nio, int fd, int actions){
	int op;
	struct epoll_event event;
	event.data.fd = fd;
	event.events = EPOLLIN;
	if(actions & ACTION_READ){
		op = EPOLL_CTL_DEL;
	}else if(actions & ACTION_WRITE){
		op = EPOLL_CTL_MOD;
	}
	return epoll_ctl(realEpoll(nio), op, fd, &event);
}

int nioWait(void* nio, struct FiredEvent* firedEvent, int firedEventLen){
	struct epoll_event events[firedEventLen];
	int changeNo = epoll_wait(realEpoll(nio), events, firedEventLen, -1);
	if(changeNo > 0){
		int index;
		for(index = 0; index < changeNo; index++){
			struct epoll_event event = events[index];
			firedEvent[index].fd = event.data.fd;
			printf("after epoll_wait: fd=%d.\n", event.data.fd);
			if(event.events & EPOLLOUT){
				firedEvent[index].action = ACTION_WRITE;
			}else if(event.events & EPOLLIN){
				firedEvent[index].action = ACTION_READ;
			}else{
				firedEvent[index].action = 0;
			}
		}
	}
	return changeNo;
}

void nioClose(void* nio){
	close(realEpoll(nio));
}
